/*
 * Copyright (C) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @addtogroup AVDemuxer
 * @{
 *
 * @brief AVDemuxer模块提供用于音视频解封装功能的函数。
 * 
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @since 10
 */


/**
 * @file native_avdemuxer.h
 *
 * @brief 声明用于音视频解封装的Native API。
 * 
 * @library libnative_media_avdemuxer.so
 * @since 10
 */

#ifndef NATIVE_AVDEMUXER_H
#define NATIVE_AVDEMUXER_H

#include <stdint.h>
#include "native_avcodec_base.h"
#include "native_avsource.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct OH_AVDemuxer OH_AVDemuxer;
typedef struct DRM_MediaKeySystemInfo DRM_MediaKeySystemInfo;

/**
 * @brief 媒体密钥系统信息回调函数指针类型。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @since 11
*/
typedef void (*DRM_MediaKeySystemInfoCallback)(DRM_MediaKeySystemInfo* mediaKeySystemInfo);

/**
 * @brief 媒体密钥系统信息回调函数指针类型。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @since 12
*/
typedef void (*Demuxer_MediaKeySystemInfoCallback)(OH_AVDemuxer *demuxer, DRM_MediaKeySystemInfo *mediaKeySystemInfo);

/**
 * @brief 通过source实例对象创建OH_AVDemuxer实例对象。可以通过调用{@link OH_AVDemuxer_Destroy}释放实例。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @param source 指向OH_AVSource实例的指针。
 * @return 返回一个指向OH_AVDemuxer实例的指针。
 * 如果执行成功，则返回指向OH_AVDemuxer实例的指针，否则返回nullptr。
 * 可能的失败原因：
 * 1. source无效，即空指针或非OH_AVSource实例。
 * @since 10
*/
OH_AVDemuxer *OH_AVDemuxer_CreateWithSource(OH_AVSource *source);

/**
 * @brief 销毁OH_AVDemuxer实例并清理内部资源。同一实例只能被销毁一次。
 * 特别提醒: 销毁的实例在被重新创建之前不能再被使用。建议实例销毁成功后将指针置为NULL。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @param demuxer 指向OH_AVDemuxer实例的指针。
 * @return 执行成功返回AV_ERR_OK, 否则返回具体错误码，请参阅{@link OH_AVErrCode}
 * 当输入的demuxer指针为空或非解封装器实例，返回{@link AV_ERR_INVALID_VAL}。
 * @since 10
*/
OH_AVErrCode OH_AVDemuxer_Destroy(OH_AVDemuxer *demuxer);

/**
 * @brief 选中指定轨道，解封装器将会从该轨道中读取数据。
 * 特别提醒: 通过多次调用接口并传入不同轨道的索引来选中多个轨道。
 * 调用OH_AVDemuxer_ReadSample时只会读取被选中的轨道中数据，同一轨道被选择多次时，接口会返回AV_ERR_OK，并且只会生效一次。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @param demuxer 指向OH_AVDemuxer实例的指针。
 * @param trackIndex 需选择的轨道的索引。
 * @return 执行成功返回AV_ERR_OK, 否则返回具体错误码，请参阅{@link OH_AVErrCode}
 * 当输入的demuxer指针为空或非解封装器实例，或demuxer没有正确的初始化，或轨道的索引超出范围，
 * 或者不支持读取轨道，返回{@link AV_ERR_INVALID_VAL}。
 * @since 10
*/
OH_AVErrCode OH_AVDemuxer_SelectTrackByID(OH_AVDemuxer *demuxer, uint32_t trackIndex);

/**
 * @brief 取消选择指定轨道，未选中的轨道的数据不会被解封装器读取。
 * 特别提醒: 通过多次调用接口并传入不同轨道的索引来取消对多个轨道的选择。
 * 同一轨道被多次取消选择时，接口会返回AV_ERR_OK，并且只会生效一次。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @param demuxer 指向OH_AVDemuxer实例的指针。
 * @param trackIndex 需取消选择的轨道的索引。
 * @return 执行成功返回AV_ERR_OK, 否则返回具体错误码，请参阅{@link OH_AVErrCode}
 * 当输入的demuxer指针为空或非解封装器实例，或者没有正确的初始化，返回{@link AV_ERR_INVALID_VAL}。
 * @since 10
*/
OH_AVErrCode OH_AVDemuxer_UnselectTrackByID(OH_AVDemuxer *demuxer, uint32_t trackIndex);

/**
 * @brief 从选中轨道中获取当前位置压缩帧及相关信息。
 * 特别提醒: 读取轨道帧数据前，轨道必须被选中。调用接口后解封装器将自动前进到下一帧。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @param demuxer 指向OH_AVDemuxer实例的指针。
 * @param trackIndex 本次读取压缩帧的轨道的索引。
 * @param sample 指向OH_AVMemory实例的指针，用于储存压缩帧数据。
 * @param info 指向OH_AVCodecBufferAttr实例的指针，用于储存压缩帧的相关信息。
 * @return 执行成功返回AV_ERR_OK, 否则返回具体错误码，请参阅{@link OH_AVErrCode}
 * 当输入的demuxer指针为空或非解封装器实例，或demuxer没有正确的初始化，或轨道的索引超出范围，
 * 或者不支持读取轨道，返回{@link AV_ERR_INVALID_VAL}。
 * 轨道的索引没有被选中，返回{@link AV_ERR_OPERATE_NOT_PERMIT}。
 * sample容量不足以存储所有帧数据，返回{@link AV_ERR_NO_MEMORY}。
 * 无法从文件中读取或解析帧，返回{@link AV_ERR_UNKNOWN}。
 * @deprecated since 11
 * @useinstead OH_AVDemuxer_ReadSampleBuffer
 * @since 10
*/
OH_AVErrCode OH_AVDemuxer_ReadSample(OH_AVDemuxer *demuxer, uint32_t trackIndex,
    OH_AVMemory *sample, OH_AVCodecBufferAttr *info);

/**
 * @brief 从选中轨道中获取当前位置压缩帧及相关信息。
 * 特别提醒: 读取轨道帧数据前，轨道必须被选中。调用接口后解封装器将自动前进到下一帧。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @param demuxer 指向OH_AVDemuxer实例的指针。
 * @param trackIndex 本次读取压缩帧的轨道的索引。.
 * @param sample 指向OH_AVBuffer实例的指针，用于储存压缩帧数据以及相关信息。
 * @return 执行成功返回AV_ERR_OK, 否则返回具体错误码，请参阅{@link OH_AVErrCode}
 * 当输入的demuxer指针为空或非解封装器实例，或demuxer没有正确的初始化，或sample为空指针，
 * 或者轨道的索引超出范围，返回{@link AV_ERR_INVALID_VAL}。
 * 轨道的索引没有被选中，返回{@link AV_ERR_OPERATE_NOT_PERMIT}。
 * sample容量不足以存储所有帧数据，返回{@link AV_ERR_NO_MEMORY}。
 * 无法从文件中读取或解析帧，返回{@link AV_ERR_UNKNOWN}。
 * @since 11
*/
OH_AVErrCode OH_AVDemuxer_ReadSampleBuffer(OH_AVDemuxer *demuxer, uint32_t trackIndex,
    OH_AVBuffer *sample);

/**
 * @brief 根据设定的跳转模式，将所有选中的轨道到指定时间附近。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @param demuxer 指向OH_AVDemuxer实例的指针。
 * @param millisecond 期望跳转位置对应的时间，单位为毫秒，该时间戳是相对文件开始的位置。
 * @param mode 跳转的模式，参考{@link OH_AVSeekMode}.
 * @return 执行成功返回AV_ERR_OK, 否则返回具体错误码，请参阅{@link OH_AVErrCode}
 * 当输入的demuxer指针为空或非解封装器实例，或demuxer没有正确的初始化，或毫秒值超出范围，返回{@link AV_ERR_INVALID_VAL}。
 * 轨道的索引没有被选中，或者资源无法seek，返回{@link AV_ERR_OPERATE_NOT_PERMIT}。
 * seek失败，返回{@link AV_ERR_UNKNOWN}。
 * @since 10
*/
OH_AVErrCode OH_AVDemuxer_SeekToTime(OH_AVDemuxer *demuxer, int64_t millisecond, OH_AVSeekMode mode);

/**
 * @brief 设置异步DRM信息回调函数。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @param demuxer 指向OH_AVDemuxer实例的指针。
 * @param callback 回调函数，详见{@link DRM_MediaKeySystemInfoCallback}。
 * @return 返回函数结果代码{@link OH_AVErrCode}：
 *         AV_ERR_OK：操作成功。
 *         AV_ERR_OPERATE_NOT_PERMIT：解复用器引擎未启动或初始化失败。
 *         AV_ERR_INVALID_VAL：解复用器实例为nullptr或无效。
 * @since 11
 * @version 1.0
 */
OH_AVErrCode OH_AVDemuxer_SetMediaKeySystemInfoCallback(OH_AVDemuxer *demuxer,
    DRM_MediaKeySystemInfoCallback callback);

/**
 * @brief 设置异步DRM信息回调函数。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @param demuxer 指向OH_AVDemuxer实例的指针。
 * @param callback 回调函数，详见{@link Demuxer_MediaKeySystemInfoCallback}。
 * @return 返回函数结果代码{@link OH_AVErrCode}：
 *         AV_ERR_OK：操作成功。
 *         AV_ERR_OPERATE_NOT_PERMIT：解复用器引擎未启动或初始化失败。
 *         AV_ERR_INVALID_VAL：解复用器实例为nullptr或无效。
 * @since 12
 * @version 1.0
 */
OH_AVErrCode OH_AVDemuxer_SetDemuxerMediaKeySystemInfoCallback(OH_AVDemuxer *demuxer,
    Demuxer_MediaKeySystemInfoCallback callback);

/**
 * @brief 获取DRM信息。
 * @syscap SystemCapability.Multimedia.Media.Spliter
 * @param demuxer 指向OH_AVDemuxer实例的指针。
 * @param mediaKeySystemInfo 指向DRM信息的指针，请参阅{@link DRM_MediaKeySystemInfo}。
 * @return 返回函数结果代码{@link OH_AVErrCode}：
 *         AV_ERR_OK：操作成功。
 *         AV_ERR_INVALID_VAL：解复用器实例为nullptr或无效，或者mediaKeySystemInfo为nullptr。
 * @since 11
 * @version 1.0
 */
OH_AVErrCode OH_AVDemuxer_GetMediaKeySystemInfo(OH_AVDemuxer *demuxer, DRM_MediaKeySystemInfo *mediaKeySystemInfo);

#ifdef __cplusplus
}
#endif

#endif // NATIVE_AVDEMUXER_H

/** @} */